"""
专家代理基类，定义所有专家代理的通用接口和行为
"""

from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from loguru import logger
import time
import json


@dataclass
class AgentResult:
    """代理结果"""
    agent_name: str
    agent_type: str
    success: bool
    findings: List[Dict[str, Any]]
    summary: str
    confidence: float
    processing_time: float
    metadata: Dict[str, Any]
    error: Optional[str] = None
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            "agent_name": self.agent_name,
            "agent_type": self.agent_type,
            "success": self.success,
            "findings": self.findings,
            "summary": self.summary,
            "confidence": self.confidence,
            "processing_time": self.processing_time,
            "metadata": self.metadata,
            "error": self.error
        }


@dataclass
class ReviewItem:
    """审查项"""
    item_id: str
    category: str
    severity: str  # 'critical', 'major', 'minor', 'info'
    description: str
    suggestion: str
    location: Optional[str] = None
    confidence: float = 1.0


class BaseAgent(ABC):
    """专家代理基类"""
    
    def __init__(self, name: str, agent_type: str, api_client, config: Dict[str, Any]):
        self.name = name
        self.agent_type = agent_type
        self.api_client = api_client
        self.config = config
        self.weight = config.get('weight', 1.0)
        
    @abstractmethod
    def process(self, data: Any, context: Dict[str, Any] = None) -> AgentResult:
        """处理数据并返回审查结果"""
        pass
    
    @abstractmethod
    def get_system_prompt(self) -> str:
        """获取系统提示词"""
        pass
    
    def create_result(
        self,
        success: bool,
        findings: List[Dict[str, Any]],
        summary: str,
        confidence: float,
        processing_time: float,
        metadata: Dict[str, Any] = None,
        error: str = None,
        locations: str = None
    ) -> AgentResult:
        """创建代理结果"""
        # 将locations信息添加到metadata中
        if metadata is None:
            metadata = {}
        if locations:
            metadata['locations'] = locations
            
        return AgentResult(
            agent_name=self.name,
            agent_type=self.agent_type,
            success=success,
            findings=findings,
            summary=summary,
            confidence=confidence,
            processing_time=processing_time,
            metadata=metadata,
            error=error
        )
    
    def create_review_item(
        self,
        item_id: str,
        category: str,
        severity: str,
        description: str,
        suggestion: str,
        location: str = None,
        confidence: float = 1.0
    ) -> ReviewItem:
        """创建审查项"""
        return ReviewItem(
            item_id=item_id,
            category=category,
            severity=severity,
            description=description,
            suggestion=suggestion,
            location=location,
            confidence=confidence
        )
    
    def format_findings(self, review_items: List[ReviewItem], default_location: str = None) -> List[Dict[str, Any]]:
        """格式化审查发现"""
        findings = []
        
        for item in review_items:
            finding = {
                "item_id": item.item_id,
                "category": item.category,
                "severity": item.severity,
                "description": item.description,
                "suggestion": item.suggestion,
                "confidence": item.confidence,
                "agent": self.name
            }
            
            # 优先使用item自身的location，然后使用默认location
            if item.location:
                finding["location"] = item.location
            elif default_location:
                finding["location"] = default_location
            else:
                finding["location"] = "未知位置"
                
            findings.append(finding)
        
        return findings
    
    def generate_summary(self, review_items: List[ReviewItem]) -> str:
        """生成审查摘要"""
        if not review_items:
            return f"{self.name}未发现问题"
        
        severity_counts = {}
        for item in review_items:
            severity_counts[item.severity] = severity_counts.get(item.severity, 0) + 1
        
        summary_parts = []
        if severity_counts.get('critical', 0) > 0:
            summary_parts.append(f"严重问题 {severity_counts['critical']} 个")
        if severity_counts.get('major', 0) > 0:
            summary_parts.append(f"重要问题 {severity_counts['major']} 个")
        if severity_counts.get('minor', 0) > 0:
            summary_parts.append(f"轻微问题 {severity_counts['minor']} 个")
        if severity_counts.get('info', 0) > 0:
            summary_parts.append(f"信息提示 {severity_counts['info']} 个")
        
        if summary_parts:
            return f"{self.name}发现：" + "，".join(summary_parts)
        else:
            return f"{self.name}未发现问题"
    
    def calculate_confidence(self, review_items: List[ReviewItem]) -> float:
        """计算整体置信度"""
        if not review_items:
            return 1.0
        
        total_confidence = sum(item.confidence for item in review_items)
        return total_confidence / len(review_items)
    
    def validate_input(self, data: Any) -> bool:
        """验证输入数据"""
        if data is None:
            logger.warning(f"{self.name}: 输入数据为空")
            return False
        return True
    
    def log_processing_start(self, data_info: str):
        """记录处理开始"""
        logger.info(f"{self.name} 开始处理: {data_info}")
    
    def log_processing_end(self, success: bool, processing_time: float, findings_count: int):
        """记录处理结束"""
        status = "成功" if success else "失败"
        logger.info(f"{self.name} 处理{status}，耗时 {processing_time:.2f}s，发现 {findings_count} 个问题")
    
    def handle_api_error(self, error: Exception, context: str = "") -> AgentResult:
        """处理API错误"""
        error_msg = f"{self.name} API调用失败: {error}"
        if context:
            error_msg += f" (上下文: {context})"
        
        logger.error(error_msg)
        
        return self.create_result(
            success=False,
            findings=[],
            summary=f"{self.name}处理失败",
            confidence=0.0,
            processing_time=0.0,
            error=str(error)
        )
    
    def parse_llm_response(self, response: str) -> List[ReviewItem]:
        """解析LLM响应为审查项"""
        review_items = []
        
        try:
            # 尝试解析JSON格式的响应
            if response.strip().startswith('{') or response.strip().startswith('['):
                data = json.loads(response)
                
                if isinstance(data, list):
                    for i, item in enumerate(data):
                        review_items.append(self._parse_review_item(item, f"{self.name}_{i}"))
                elif isinstance(data, dict):
                    if 'findings' in data:
                        for i, item in enumerate(data['findings']):
                            review_items.append(self._parse_review_item(item, f"{self.name}_{i}"))
                    else:
                        review_items.append(self._parse_review_item(data, f"{self.name}_0"))
            else:
                # 处理文本格式的响应
                review_items = self._parse_text_response(response)
                
        except json.JSONDecodeError:
            # 如果不是JSON格式，按文本处理
            review_items = self._parse_text_response(response)
        except Exception as e:
            logger.error(f"{self.name} 解析响应失败: {e}")
            # 创建一个通用的审查项
            review_items.append(self.create_review_item(
                item_id=f"{self.name}_parse_error",
                category="解析错误",
                severity="info",
                description=f"响应解析失败: {str(e)}",
                suggestion="请检查响应格式"
            ))
        
        return review_items
    
    def _parse_review_item(self, item_data: Dict[str, Any], default_id: str) -> ReviewItem:
        """解析单个审查项"""
        return self.create_review_item(
            item_id=item_data.get('item_id', default_id),
            category=item_data.get('category', '未分类'),
            severity=item_data.get('severity', 'info'),
            description=item_data.get('description', ''),
            suggestion=item_data.get('suggestion', ''),
            location=item_data.get('location'),
            confidence=item_data.get('confidence', 1.0)
        )
    
    def _parse_text_response(self, response: str) -> List[ReviewItem]:
        """解析文本格式的响应"""
        review_items = []
        
        # 简单的文本解析逻辑
        lines = response.strip().split('\n')
        current_item = {}
        item_count = 0
        
        for line in lines:
            line = line.strip()
            if not line:
                continue
                
            # 检查是否是新的问题项
            if any(keyword in line.lower() for keyword in ['问题', '建议', '发现', '错误', '警告']):
                if current_item:
                    # 保存当前项
                    review_items.append(self._create_item_from_text(current_item, item_count))
                    item_count += 1
                    current_item = {}
                
                current_item['description'] = line
            else:
                # 添加到当前项的描述中
                if 'description' in current_item:
                    current_item['description'] += ' ' + line
                else:
                    current_item['description'] = line
        
        # 处理最后一个项
        if current_item:
            review_items.append(self._create_item_from_text(current_item, item_count))
        
        # 如果没有解析出任何项，创建一个通用项
        if not review_items and response.strip():
            review_items.append(self.create_review_item(
                item_id=f"{self.name}_general",
                category="一般审查",
                severity="info",
                description=response.strip()[:200],  # 限制长度
                suggestion="请参考详细描述"
            ))
        
        return review_items
    
    def _create_item_from_text(self, item_data: Dict[str, str], index: int) -> ReviewItem:
        """从文本数据创建审查项"""
        description = item_data.get('description', '')
        
        # 简单的严重性判断
        severity = 'info'
        if any(keyword in description.lower() for keyword in ['严重', '错误', '失败', 'critical', 'error']):
            severity = 'critical'
        elif any(keyword in description.lower() for keyword in ['重要', '警告', 'major', 'warning']):
            severity = 'major'
        elif any(keyword in description.lower() for keyword in ['轻微', 'minor']):
            severity = 'minor'
        
        return self.create_review_item(
            item_id=f"{self.name}_{index}",
            category="文本解析",
            severity=severity,
            description=description,
            suggestion="请根据描述进行相应处理"
        )